package com.platform.task.core.impl;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledFuture;

import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.util.StringUtils;

import com.platform.task.core.Task;
import com.platform.task.core.contants.TaskContants;
import com.platform.task.core.enums.TaskTypeEnum;

@SuppressWarnings("rawtypes")
public class ThreadPoolTaskSchedulerComponent extends ThreadPoolTaskScheduler {
	private static ThreadPoolTaskSchedulerComponent threadPoolTaskSchedulerComponent;

	private Map<String, ThreadPoolTaskExecutor> executorTaskMap = new ConcurrentHashMap<String, ThreadPoolTaskExecutor>();

	private Map<String, ThreadPoolTaskScheduler> schedulerTaskMap = new ConcurrentHashMap<String, ThreadPoolTaskScheduler>();

	private Map<String, ScheduledFuture> scheduledFutureMap = new ConcurrentHashMap<String, ScheduledFuture>();

	public void registerScheduleWithFixedDelay(Task task, long delay, TaskTypeEnum taskType) {
		if (schedulerTaskMap.get(task.getTaskName()) == null) {
			ThreadPoolTaskScheduler threadPoolTaskScheduler=new ThreadPoolTaskScheduler();
			threadPoolTaskScheduler.initialize();
			ScheduledFuture future = threadPoolTaskScheduler.scheduleWithFixedDelay(task, delay);
			scheduledFutureMap.put(task.getTaskName(), future);
		}
	}

	public void registerSchedule(Task task, Trigger trigger, TaskTypeEnum taskType) {
		if (schedulerTaskMap.get(task.getTaskName()) == null) {
			ThreadPoolTaskScheduler threadPoolTaskScheduler=new ThreadPoolTaskScheduler();
			threadPoolTaskScheduler.initialize();
			ScheduledFuture future = threadPoolTaskScheduler.schedule(task, trigger);
			scheduledFutureMap.put(task.getTaskName(), future);
		}
	}

	public void destorySchedule(String taskName) {
		ThreadPoolTaskScheduler threadPoolTaskScheduler = schedulerTaskMap.get(taskName);
		if (threadPoolTaskScheduler != null) {
			threadPoolTaskScheduler.destroy();
		}
		ScheduledFuture future = scheduledFutureMap.get(taskName);
		if (future != null) {
			future.cancel(true);
		}
	}

	public void stopSchedule(String taskName) {
		ScheduledFuture future = scheduledFutureMap.get(taskName);
		if (future != null) {
			future.cancel(true);
		}
	}

	private ThreadPoolTaskSchedulerComponent() {
		ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
		threadPoolTaskExecutor.setQueueCapacity(20000);
		threadPoolTaskExecutor.setCorePoolSize(Runtime.getRuntime().availableProcessors() / 2);
		threadPoolTaskExecutor.setMaxPoolSize(Runtime.getRuntime().availableProcessors());
		executorTaskMap.put(TaskContants.DEFAULT_TASK, threadPoolTaskExecutor);
	}

	public static ThreadPoolTaskSchedulerComponent getInstance() {
		if (threadPoolTaskSchedulerComponent == null) {
			return new ThreadPoolTaskSchedulerComponent();
		}
		return threadPoolTaskSchedulerComponent;
	}

	public ThreadPoolTaskExecutor getThreadPool(String name, int poolSize) {
		if (StringUtils.isEmpty(name)) {
			return executorTaskMap.get(TaskContants.DEFAULT_TASK);
		}
		ThreadPoolTaskExecutor threadPoolTaskExecutor = executorTaskMap.get(name);
		if (threadPoolTaskExecutor == null) {
			synchronized (executorTaskMap) {
				threadPoolTaskExecutor = executorTaskMap.get(name);
				if (threadPoolTaskExecutor == null) {
					threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
					threadPoolTaskExecutor.setCorePoolSize(poolSize);
					threadPoolTaskExecutor.setMaxPoolSize(poolSize);
					threadPoolTaskExecutor.setQueueCapacity(10000);
					threadPoolTaskExecutor.setThreadNamePrefix(name + "-");
					threadPoolTaskExecutor.initialize();
					executorTaskMap.put(name, threadPoolTaskExecutor);
				}
			}
		}
		return threadPoolTaskExecutor;
	}
}
